/*
 * $Id: StringUtils.java 15 2014-08-17 14:20:24Z ratking $
 *
 * Copyleft (C) 2014 RatKing. All wrongs reserved.
 */
package cn.ratking.demo.jaws6.common;

import java.io.UnsupportedEncodingException;

/**
 * 字符串实用工具类
 */
public class StringUtils {

    /**
     * 截短字符串，返回长度不大于maxLen的子串.
     * 如果所给源字符串长度过大，则大于maxLen的后面部分用“…”替换
     *
     * @param str 源字符
     * @param maxLen 截短后的最大长度(按字节计算，一个汉字或全角标点长度2，一个英文、数字或半角标点长度1)
     * @return 截短后的字符串
     */
    public static String trim(String str, int maxLen) {
        return getLimitLengthString(str, maxLen, "…");
    }

    /**
     * 截短字符串，返回长度不大于maxLen的子串.
     * 如果所给源字符串长度过大，则大于maxLen的后面部分用symbol替换。
     * 如果为空(null)则返回""。
     *
     * @param str 源字符
     * @param maxLen 截短后的最大长度(按字节计算，一个汉字或全角标点长度2，一个英文、数字或半角标点长度1)
     * @param symbol 替换符号
     * @return 截短后的字符串
     */
    public static String getLimitLengthString(String str, int maxLen, String symbol) {
        if (str == null) {
            return "";
        }
        if (symbol == null) {
            symbol = "";
        }
        try {
            byte b[] = str.getBytes("GBK");
            if (b.length <= maxLen) {
                return str;
            }

            // 返回字符串的长度应小于或等于此长度
            int len = maxLen - symbol.getBytes("GBK").length;

            // 使用二分法查找算法
            int index = 0;
            // 记录第一个元素
            int lower = 0;
            // 记录最后一个元素
            int higher = str.length() - 1;
            while (lower <= higher) {
                // 记录中间元素，用两边之和除2
                index = (lower + higher) / 2;
                int tmpLen = str.substring(0, index).getBytes("GBK").length;
                if (tmpLen == len) {
                    // 如果得到的与要查找的相等，则break退出
                    break;
                } else if (tmpLen < len) {
                    // 如果得到的要小于查找的，就用下标加1
                    lower = index + 1;
                } else {
                    // 如果得到的要大于查找的，就用下标减1
                    higher = index - 1;
                }
            }
            if (lower > higher) {
                index = higher;
            }

            // 调用String构造方法以避免substring导致的内存泄露
            return new String(str.substring(0, index) + symbol);
        } catch (UnsupportedEncodingException uee) {
            String errorMessage = "内部错误：本计算机的Java环境不支持GBK编码！";
            throw new IllegalStateException(errorMessage, uee);
        }
    }
}
